use std::option::Option;
use crate::context::agent::AGENT_CONTEXT_FILE_ZIP_NAME;
use crate::context::{get_file_or_create, read_to_string};
use crate::context::license_gen::generate_license;
use crate::context::plugins::get_plugin_list;
use crate::context::products::get_products;
use crate::AppResult;
use axum::extract::{Path, Query};
use axum::response::IntoResponse;
use axum::Json;
use axum_extra::response::FileStream;
use serde::{Deserialize, Serialize};
use tokio_util::io::ReaderStream;
pub fn registry(app: axum::Router) -> axum::Router{
    app.route("/api/products", axum::routing::get(products))
        .route("/api/plugins", axum::routing::get(plugins))
        .route("/install/{debug}", axum::routing::get(install_agent))
        .route("/install", axum::routing::get(install_agent))
        .route("/uninstall/{debug}", axum::routing::get(uninstall_agent))
        .route("/uninstall", axum::routing::get(uninstall_agent))
        .route("/ja-netfilter", axum::routing::get(download_agent))
        .route("/license-code/generate", axum::routing::get(generate_license_by_get))
        .route("/license-code/generate", axum::routing::post(generate_license_by_post))
}

async fn products() -> impl IntoResponse {
    Json(get_products().await.clone())
}

async fn plugins() -> impl IntoResponse {
    Json(get_plugin_list().await.clone())
}
async fn install_agent(option:Option<Path<String>>) -> AppResult<String> {
    let mut path = "external/scripts/install.txt";
    if option.is_some() && option.unwrap().0== "debug" {
         path = "external/scripts/install_debug.txt";
    }
    let script = read_to_string(&mut get_file_or_create(path).await?).await?;
    Ok(script)
}
async fn uninstall_agent(option:Option<Path<String>>) -> AppResult<String> {
    let mut path = "external/scripts/uninstall.txt";
    if option.is_some() && option.unwrap().0== "debug" {
        path = "external/scripts/uninstall_debug.txt";
    }
    let script = read_to_string(&mut get_file_or_create(path).await?).await?;
    Ok(script)
}
async fn download_agent() -> AppResult<impl IntoResponse>{
    let result = get_file_or_create(AGENT_CONTEXT_FILE_ZIP_NAME).await?;
    let reader_stream = ReaderStream::new(result);
    Ok(FileStream::new(reader_stream).file_name("ja-netfilter.zip").into_response())
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GenerateLicenseReqBody {
    /// 许可证名称（公司或组织名称）
    #[serde(rename = "licenseName")]
    pub license_name: String,

    /// 被授权人名称（使用者名称）
    #[serde(rename = "assigneeName")]
    pub assignee_name: String,

    /// 过期日期（格式：yyyy-MM-dd）
    #[serde(rename = "expiryDate")]
    pub expiry_date: String,

    /// 产品代码（多个代码用逗号分隔，为空时包含所有产品）
    #[serde(rename = "productCode")]
    pub product_code: Option<String>,
}
async fn generate_license_by_get(Query(request):Query<GenerateLicenseReqBody>)-> AppResult<String>{
    generate_license_by_post(Json::from(request)).await
}
async fn generate_license_by_post(Json(request):Json<GenerateLicenseReqBody>)-> AppResult<String>{
    let product_code_set = match request.product_code {
        None => {
            let vec1 = get_products().await.iter()
                .filter(|product| !product.product_code.is_empty())
                .flat_map(|product| {
                    product.product_code.trim().split(",")
                }).map(|product_code| product_code.to_string())
                .collect::<Vec<String>>();
            let vec2 = get_plugin_list().await.iter()
                .filter(|plugin| !plugin.product_code.is_empty())
                .map(|plugin| plugin.product_code.to_string())
                .collect::<Vec<String>>();
            vec1.into_iter().chain(vec2.into_iter()).collect::<Vec<String>>()
        }
        Some(code) => {
            code.split( ",").into_iter()
                .map(|product_code| product_code.trim().to_string())
                .collect()
        }
    };
    generate_license(request.license_name, request.assignee_name, request.expiry_date, product_code_set).await
}
